// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

#include "cangjie/AST/Match.h"
#include "cangjie/AST/Walker.h"

#include "NodeCast.h"
#include "Rules/Rule.h"

#include "Rules/ArrayInitCallExprMatchRule.h"

using namespace Cangjie::AST;

namespace CangjieMigrator::Rules {

ArrayInitCallExprMatchRule::ArrayInitCallExprMatchRule(
    std::string elementName, std::string funcType, std::string funcName)
    : CallExprMatchRule(std::move(elementName), std::move(funcType), std::move(funcName))
{}

using Cangjie::AST::Walker;

static const ArrayLit *TryGetArrayLit(const Node &node)
{
    const Node *n = &node;
    while (n) {
        switch (n->astKind) {
            case ASTKind::ARRAY_LIT:
                return Cast<ASTKind::ARRAY_LIT>(n);
            case ASTKind::PAREN_EXPR:
                n = Cast<ASTKind::PAREN_EXPR>(n)->expr.get();
                break;
            default:
                return nullptr;
        }
    }
    return nullptr;
}

std::vector<Actions::Action> ArrayInitCallExprMatchRule::GenerateAction(UpdateInstance::File &file,
    const ExtractedInfo &info, const std::string &update, const Rule *rule) const
{
    if (info.node.astKind != ASTKind::CALL_EXPR) {
        return CallExprMatchRule::GenerateAction(file, info, update, rule);
    }

    const auto &node = Cast<ASTKind::CALL_EXPR>(info.node);
    if (node.args.size() != 1) {
        return CallExprMatchRule::GenerateAction(file, info, update, rule);
    }
    const auto arg = node.args[0].get();
    if (!arg) {
        return CallExprMatchRule::GenerateAction(file, info, update, rule);
    }

    if (arg->expr != nullptr && TryGetArrayLit(*arg->expr)) {
        return {};
    }

    return CallExprMatchRule::GenerateAction(file, info, update, rule);
}

std::unique_ptr<MatchRule> ArrayInitCallExprMatchRule::TryBuild(const TomlConfig &config)
{
    if (config.title != "ArrayInitCallExpr") {
        return nullptr;
    }
    GET_VALUE_IF_EMPTY_RETURN_NULL(config, elementName);
    GET_VALUE_IF_EMPTY_RETURN_NULL(config, funcType);
    GET_VALUE_IF_EMPTY_RETURN_NULL(config, funcName);
    return std::make_unique<ArrayInitCallExprMatchRule>(elementName, funcType, funcName);
}

} // namespace CangjieMigrator::Rules
